import json
from rest_framework.views import APIView
from rest_framework import status, permissions
from ..models import Bot, Conversation, BotPublishHistory
from ..serializers import BotSerializer, ConversationSerializer
import requests  # type: ignore
from django.conf import settings  # 引入 settings
from .BaseResponse import BaseResponse
from ..services.prompt_service import PromptGenerationService
import re
import logging

# 配置日志记录器
logger = logging.getLogger(__name__)

# 添加关键词列表用于检测是否生成笔记
KEYWORDS = [
    '笔记', '记录', '保存', '生成', '总结', '要点', '备忘', '日志', '写下', '记下', '记录下来', '创建笔记', '生成笔记',
    '保存笔记', '总结内容', '要点记录', '写笔记', '记笔记', '笔记本', '笔记内容', '笔记记录', '笔记生成', '笔记保存', '计划',
    '整理', '归纳', '小结', '摘要', '提炼', '提取', '汇总', '归纳要点', '提取重点', '记在笔记中', '做个记录',
    '做个笔记', '帮我记一下', '帮我整理', '帮我总结', '帮我提取', '可以帮我记录', '整理成笔记', '转为笔记'
]

# 扩展关键词，增加与计划相关的词汇
PLAN_KEYWORDS = [
    '计划', '规划', '安排', '日程', '训练', '学习计划', '进度', '阶段', '目标', '任务', '每日任务', '每周任务', '行动项',
    '时间表', '时间安排', '训练方案', '练习方案', '步骤', '路线图', '学习路径', '成长路径', '技能提升', '提升计划',
    '入门计划', '初学者计划', '进阶计划', '训练周期', '学习周期', '复习计划', '实践计划', '周计划', '月计划'
]

# 合并关键词列表
KEYWORDS.extend(PLAN_KEYWORDS)

# 添加判断是否生成笔记的函数
def should_create_note(user_message, bot_response=None):
    """判断用户输入或AI回复是否需要生成笔记的智能判断函数"""
    if not user_message and not bot_response:
        return False
        
    # 1. 明确的用户意图检测 - 用户主动请求记录或计划
    if user_message:
        # 直接关键词检测
        explicit_note_keywords = ['做笔记', '记录下来', '保存这个', '生成笔记', '转为笔记']
        if any(keyword in user_message.lower() for keyword in explicit_note_keywords):
            return True
            
        # 计划请求检测 - 增强模式匹配识别更多计划请求格式
        plan_request_patterns = [
            '帮我制定', '设计.*?计划', '帮我规划', '制定.*?方案', 
            '需要一个计划', '想要一份计划', '学习计划', '训练方案',
            '安排.*?计划', '制定.*?课程', '希望有.*?计划', '给我.*?计划'
        ]
        if any(re.search(pattern, user_message.lower()) for pattern in plan_request_patterns):
            return True
    
    # 2. 回复内容结构化检测 - AI生成了高价值的结构化内容
    if bot_response:
        # 检查周计划格式 - 高优先级检测
        week_plan_pattern = r'###\s+(周[一二三四五六日]|星期[一二三四五六日])'
        if re.search(week_plan_pattern, bot_response):
            return True
            
        # 检查分日计划格式
        day_plan_sections = re.findall(r'(周[一二三四五六日]|星期[一二三四五六日]).*?[:：]', bot_response)
        if len(day_plan_sections) >= 3:  # 至少有三天的计划安排
            return True
        
        # 长度与结构结合判断
        is_structured = False
        
        # 检查结构化标记 (精简高效模式)
        structure_markers = [
            # 核心结构标记
            r'(##+\s+.+)',                # 标题和子标题
            r'(\d+\.\s+.+)',              # 编号列表
            r'(-\s+.+)',                  # 项目符号列表
            r'(•\s+.+)',                  # 圆点项目符号
            r'(\*\s+.+)',                 # 星号项目符号
            
            # 时间/数量模式
            r'(\d+[:：]\d+)',             # 时间格式
            r'(\d+[组次分钟小时])',        # 数量单位
            r'(每[天周月][^，。；!?]*\d+)', # 时间频率
            
            # 常见计划格式
            r'(###\s+.+[计划指南指导概览安排步骤])',  # 计划相关小标题
            r'(第[一二三四五六七八九十\d]+(阶段|周|天|部分))', # 阶段标记
            r'([周星期][一二三四五六日]([：:][^，。；!?]*|$))', # 周计划日期格式
            
            # 带计量的项目
            r'(-\s+.*?[:：]\s*\d+.*?[分钟小时次篇个])',  # 带时间/数量的项目
            r'(•\s+.*?[:：]\s*\d+.*?[分钟小时次篇个])',  # 带时间/数量的圆点项目
        ]
        
        for pattern in structure_markers:
            if re.search(pattern, bot_response):
                is_structured = True
                break
                
        # 内容价值判断 - 高信息密度结构化内容
        if len(bot_response) > 300 and is_structured:
            return True
            
        # 检测典型的计划内容和格式 (精简高效模式)
        plan_content_indicators = [
            # 计划核心特征
            r'([计划规划方案安排]+[^，。；!?]{0,10}(每|分配|时间))',  # 计划时间关联
            r'((训练|学习|工作|复习)[^，。；!?]{0,10}(方法|要点|内容))', # 内容方法关联
            r'((上午|下午|晚上|早上)[^，。；!?]{0,10}(分钟|小时|练习))', # 时段活动关联
            
            # 计划数量特征
            r'(\d+组[^，。；!?]{0,5}\d+[次分钟])',  # 组数次数
            r'(\d+[项个][^，。；!?]{0,5}任务)',     # 任务数量
            r'(每[天周日][^，。；!?]{0,10}\d+[次分钟小时])', # 频率数量
            
            # 计划领域特征
            r'(学习|训练|锻炼|工作|提升|成长)[计划方案]',  # 领域计划
            r'(健身|职业|能力|技能|知识)[提升规划]',      # 能力提升
            r'(入门|进阶|高级|专业|基础)[教程指南]',      # 水平进阶
            
            # 辅助特征
            r'(建议|指导|要点|步骤|注意|技巧)[：:].{5,}',  # 指导性内容
            r'(第[一二三四五六七八九十\d]+[天周日])[^，。；!?]{0,20}', # 时间安排
        ]
        
        # 计数匹配的计划指标
        plan_indicators_count = 0
        for pattern in plan_content_indicators:
            if re.search(pattern, bot_response):
                plan_indicators_count += 1
                
        # 如果匹配到多个计划指标，更可能是值得保存的计划
        if plan_indicators_count >= 2:
            return True
    
    # 3. 检查原有的结构化内容模式 (保留关键的原有模式)
    if bot_response and len(bot_response) > 400:
        # 基础结构模式
        basic_structures = ["##", "###", "1.", "2.", "- ", "* ", "• "]
        if any(pattern in bot_response for pattern in basic_structures):
            # 额外检查是否同时包含计划相关词汇
            plan_related = [
                # 核心计划词
                "计划", "安排", "任务", "步骤", "方案", "攻略", "指南",
                
                # 时间与频率
                "每日", "每周", "每月", "周期", "阶段", "天", "周",
                
                # 学习与训练
                "学习", "训练", "练习", "复习", "教程", "课程", "讲解",
                
                # 工作与能力
                "工作", "职业", "能力", "提升", "成长", "技能", "规划",
                
                # 健康与生活
                "健身", "饮食", "生活", "作息", "健康", "习惯", "管理",
                
                # 心态与情绪
                "心态", "压力", "情绪", "调节", "平衡", "缓解"
            ]
            if any(word in bot_response for word in plan_related):
                return True
    
    # 4. 高级情境判断 - 适用于更复杂的对话场景
    # 如果用户提问简短(<100字)但回复很长(>500字)且结构化，很可能是值得保存的信息
    if user_message and bot_response:
        if len(user_message) < 100 and len(bot_response) > 500:
            # 检查回复中的结构标记和分段数量
            paragraphs = bot_response.split('\n\n')
            if len(paragraphs) > 4:  # 多个段落的结构化内容
                return True
        
        # 检测简短但高价值的计划 - 针对简洁计划模式
        if len(bot_response) >= 150 and len(bot_response) <= 500:
            # 快速结构判断
            newline_count = bot_response.count('\n')
            bullet_points = len(re.findall(r'[-•*]\s+', bot_response))
            headers = len(re.findall(r'#+\s+', bot_response))
            numbered_items = len(re.findall(r'\d+\.\s+', bot_response))
            
            # 检测结构化特征
            structure_score = (newline_count * 0.5) + (bullet_points * 1.5) + (headers * 2) + (numbered_items * 1.5)
            
            if structure_score >= 6:
                # 高效检测价值指标词
                indicators = {
                    '时间': ['分钟', '小时', '天', '周', '月', '上午', '下午', '晚上', '早晨'],
                    '数量': ['次', '组', '篇', '项', '个', '遍', '回'],
                    '指导': ['建议', '指导', '注意', '方法', '步骤', '技巧', '要点', '关键', '重点']
                }
                
                # 快速计算指标词特征得分
                indicator_score = 0
                for category, words in indicators.items():
                    for word in words:
                        if word in bot_response:
                            indicator_score += 1
                            # 避免过度计算
                            if indicator_score >= 4:
                                return True
                
                # 如果结构和指标都足够好，判定为有价值的计划
                if indicator_score >= 3:
                    return True
    
    return False

class BotConversationView(APIView):
    permission_classes = [permissions.IsAuthenticated]  # 确保用户已登录

    def post(self, request):
        # 获取 Coze 平台的令牌（从环境变量中获取）
        coze_access_token = settings.COZE_ACCESS_TOKEN
        if not coze_access_token:
            return BaseResponse.error("Missing Coze access token", status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        # 获取请求数据
        bot_id = request.data.get("bot_id")
        user_id = request.data.get("user_id")
        user_message = request.data.get("user_message")

        # 验证参数
        if not bot_id or not user_id or not user_message:
            return BaseResponse.error("Missing required parameters: bot_id, user_id, user_message")

        # 确保智能体属于当前用户
        try:
            bot = Bot.objects.get(bot_id=bot_id, user=request.user)
        except Bot.DoesNotExist:
            return BaseResponse.error("Bot not found", status=status.HTTP_404_NOT_FOUND)

        # 调用 Coze API 创建对话
        url = "https://api.coze.cn/v3/chat?"
        headers = {
            "Authorization": f"Bearer {coze_access_token}",
            "Content-Type": "application/json"
        }
        
        # 添加简洁专业性提示，增强上下文理解能力
        plan_focused_system_prompt = """你是专业AI助手，擅长对话连贯和直接生成计划。

对话原则:
1. 利用历史记录避免重复询问
2. 记住用户偏好和目标
3. 保持多轮对话一致性
4. 理解上下文指代

计划生成:
1. 识别计划需求时立即生成方案，不询问可推断信息
2. 计划分"概览"和"详细指导"两部分，概览按日期组织，详细指导极度简洁
3. 详细指导部分：消除冗余描述，使用短句，直接给出关键操作和数据
4. 详细指导中不要使用周一/周二等日期词语，改用训练类型或内容类型作为标题
5. 避免在详细指导中使用完整句子，优先使用命令式短语
6. 清晰标明数字参数（次数、组数、时间）但不需过多解释原理

基于上下文提供精准专业的回答和计划。"""
        
        data = {
            "bot_id": bot.bot_id,
            "user_id": user_id,
            "stream": True,
            "auto_save_history": True,
            "additional_messages": [
                {
                    "role": "system",
                    "content": plan_focused_system_prompt,
                    "content_type": "text"
                }
            ]
        }

        # 获取历史对话记录以增强上下文理解
        try:
            # 获取会话ID（如果有）
            session_id = request.data.get("session_id")
            
            # 查询历史对话
            history_conversations = []
            
            # 基于会话ID获取对话，提高上下文连贯性
            if session_id:
                try:
                    history_conversations = Conversation.objects.filter(
                        bot=bot, user_id=user_id, session_id=session_id
                    ).order_by('-created_at')[:5]  # 获取最近5条同一会话的对话
                    
                    # 反转列表使其按时间顺序排列
                    history_conversations = list(reversed(history_conversations))
                    logger.info(f"基于会话ID {session_id} 获取了 {len(history_conversations)} 条历史记录")
                except Exception as e:
                    logger.warning(f"通过会话ID获取历史对话失败: {str(e)}")
            
            # 如果没有通过会话ID获取到记录，则使用常规方式获取
            if not history_conversations:
                history_conversations = Conversation.objects.filter(
                    bot=bot, user_id=user_id
                ).order_by('-created_at')[:3]  # 限制为最近3轮对话
                
                # 反转列表使其按时间顺序排列（从早到晚）
                history_conversations = list(reversed(history_conversations))
                logger.info(f"基于时间顺序获取了 {len(history_conversations)} 条历史记录")
            
            # 构建历史对话消息
            history_messages = []
            
            for conv in history_conversations:
                # 添加用户消息
                if conv.user_message:
                    history_messages.append({
                        "role": "user",
                        "content": conv.user_message,
                        "content_type": "text"
                    })
                
                # 添加机器人回复
                if conv.bot_response:
                    # 如果回复过长，进行截断以避免token过多
                    bot_resp = conv.bot_response
                    if len(bot_resp) > 1000:
                        bot_resp = bot_resp[:1000] + "...(内容已简化)"
                    
                    history_messages.append({
                        "role": "assistant",
                        "content": bot_resp,
                        "content_type": "text"
                    })
            
            # 将历史消息添加到请求中
            if history_messages:
                # 添加历史消息
                data["additional_messages"].extend(history_messages)
                logger.info(f"已添加 {len(history_messages)} 条历史消息到对话上下文")
            
            # 添加最新的用户消息
            data["additional_messages"].append({
                "role": "user",
                "content": user_message,
                "content_type": "text"
            })
            
        except Exception as e:
            logger.error(f"获取历史对话失败: {str(e)}")
            # 添加当前用户消息，确保即使历史获取失败，当前请求仍能继续
            data["additional_messages"].append({
                "role": "user",
                "content": user_message,
                "content_type": "text"
            })

        try:
            response = requests.post(url, json=data, headers=headers, stream=True)
            if response.status_code == 200:
                # 处理流式响应
                stream_data = []
                bot_response = ""  # 用于累积智能体的回复
                final_content = None  # 用于存储最后的 conten
                for line in response.iter_lines():
                    if line:
                        # 解析 SSE 格式的行
                        line = line.decode("utf-8")
                        if line.startswith("data:"):
                            try:
                                # 提取 JSON 数据
                                json_data = line[5:].strip()
                                # 检查是否是有效的 JSON
                                try:
                                    chunk = json.loads(json_data)
                                except json.JSONDecodeError:
                                    # 如果不是有效的 JSON，跳过
                                    continue
                                stream_data.append(chunk)
                                # 提取智能体的回复
                                if chunk.get("event") == "conversation.message.delta" and chunk.get("data", {}).get(
                                        "content"):
                                    bot_response += chunk["data"]["content"]
                                # 检查是否是最后一条消息
                                if chunk.get("type") == "answer" and chunk.get("content"):
                                    final_content = chunk.get("content")
                            except Exception as e:
                                continue

                # 检查是否成功获取了智能体的回复
                print(f"Final content: {final_content}")
                if final_content:
                    bot_response = final_content
                elif bot_response:
                    pass  # 使用累积的回复
                else:
                    # 如果没有获取到智能体的回复
                    return BaseResponse.error("Failed to create bot", status=status.HTTP_500_INTERNAL_SERVER_ERROR)

                # 根据用户消息和AI回复判断是否生成笔记
                create_note = should_create_note(user_message, bot_response)

                # 生成笔记标题（如果需要生成笔记）
                note_title = None
                if create_note:
                    try:
                        # 先尝试使用AI生成标题
                        note_title = PromptGenerationService.generate_note_title_with_ai(bot_response)
                    except Exception as e:
                        # 如果AI生成失败，使用简单方法生成
                        note_title = PromptGenerationService.generate_note_title(bot_response)

                # 保存对话到数据库
                conversation = Conversation(
                    bot=bot,
                    user_id=user_id,
                    user_message=user_message,
                    bot_response=bot_response,
                    stream_data=stream_data,
                    stream_completed=True,
                    create_note=create_note  # 添加create_note字段
                )
                
                # 如果请求中包含session_id，保存到对话记录中
                if session_id and hasattr(conversation, 'session_id'):
                    conversation.session_id = session_id
                    
                conversation.save()

                # 序列化返回数据
                serializer = ConversationSerializer(conversation)
                response_data = serializer.data
                response_data['create_note'] = 1 if create_note else 0  # 添加create_note字段到返回数据中

                # 如果需要生成笔记，添加标题到返回数据
                if create_note and note_title:
                    response_data['note_title'] = note_title

                return BaseResponse.success(response_data)
            else:
                error_data = response.json()
                return BaseResponse.error(error_data)
        except Exception as e:  # 处理请求异常
            return BaseResponse.error("Failed to create conversation", status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def get(self, request):
        # 获取查询参数中的bot_id
        bot_id = request.query_params.get('bot_id')

        # 基础查询：获取当前用户的对话
        query = Conversation.objects.filter(bot__user=request.user)

        # 如果提供了bot_id，则进一步过滤特定智能体的对话
        if bot_id:
            try:
                # 确保智能体属于当前用户
                bot = Bot.objects.get(bot_id=bot_id, user=request.user)
                query = query.filter(bot=bot)
            except Bot.DoesNotExist:
                return BaseResponse.error("Bot not found", status=status.HTTP_404_NOT_FOUND)

        # 序列化并返回结果
        serializer = ConversationSerializer(query, many=True)
        return BaseResponse.success(serializer.data)